import json
import os
import threading
import tkinter as tk
from tkinter import messagebox, ttk, filedialog
from datetime import datetime
import time
import queue
import struct
import binascii

class CANUpgrade:
    def __init__(self, root, network_manager, message_display, timestamp_var):
        self.root = root
        self.network_manager = network_manager
        self.message_display = message_display
        self.timestamp_var = timestamp_var
        self.count_label = None
        self.id_list_label = None
        self.upgrade_in_progress = False
        self.stop_jump_retry = False
        self.progress_var = tk.StringVar()
        self.bin_data = None
        self.upgrade_state = "IDLE"
        self.current_frame = 0
        self.upgrade_response_received = False
        self.erase_retry_count = 0  # 擦除重试计数器
        self.MAX_ERASE_RETRY = 3    # 最大擦除重试次数

    def show_can_upgrade_dialog(self):
        """显示CAN转发升级对话框"""
        dialog = tk.Toplevel(self.root)
        dialog.title("CAN固件升级")
        
        # 设备ID选择
        tk.Label(dialog, text="设备ID:").grid(row=0, column=0, padx=5, pady=5)
        self.id_combobox = ttk.Combobox(dialog)
        self.id_combobox.grid(row=0, column=1, padx=5, pady=5)
        
        # 固件文件选择
        tk.Button(dialog, text="选择固件文件", command=self.open_bin_file).grid(row=1, column=0, padx=5, pady=5)
        
        # 升级按钮
        tk.Button(dialog, text="开始升级", command=self.start_firmware_upgrade).grid(row=1, column=1, padx=5, pady=5)
        
        # 进度显示
        tk.Label(dialog, textvariable=self.progress_var).grid(row=2, column=0, columnspan=2)
        
        # 红外/称重统计按钮
        tk.Button(dialog, text="红外统计", command=self.send_infrared_count).grid(row=3, column=0, padx=5, pady=5)
        tk.Button(dialog, text="称重统计", command=self.send_weight_count).grid(row=3, column=1, padx=5, pady=5)
        
        # 统计结果显示
        tk.Label(dialog, text="统计数量:").grid(row=4, column=0, padx=5, pady=5)
        self.count_label = tk.Label(dialog, text="0")
        self.count_label.grid(row=4, column=1, padx=5, pady=5)
        
        tk.Label(dialog, text="ID列表:").grid(row=5, column=0, padx=5, pady=5)
        self.id_list_label = tk.Label(dialog, text="[]")
        self.id_list_label.grid(row=5, column=1, padx=5, pady=5)

    def open_bin_file(self):
        """打开固件文件"""
        file_path = filedialog.askopenfilename(filetypes=[("Bin Files", "*.bin")])
        if file_path:
            try:
                with open(file_path, "rb") as f:
                    self.bin_data = f.read()
                messagebox.showinfo("成功", f"已加载固件文件: {os.path.basename(file_path)}")
            except Exception as e:
                messagebox.showerror("错误", f"加载固件文件失败: {str(e)}")

    def start_firmware_upgrade(self):
        """开始固件升级流程"""
        if not hasattr(self, 'bin_data') or not self.bin_data:
            messagebox.showwarning("警告", "请先选择固件文件")
            return

        self.upgrade_in_progress = True
        self.upgrade_state = "JUMP"
        self._send_jump_command()

    def _display_sent_message(self, message, raw_data=None):
        """显示发送的消息，可选显示原始数据"""
        timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
        if isinstance(message, dict):
            msg_str = json.dumps(message)
            self.message_display.insert(tk.END, f"[{timestamp}] 发送: {msg_str}\n")
        else:
            self.message_display.insert(tk.END, f"[{timestamp}] {message}\n")
        
        # 如果有原始数据，显示原始二进制内容
        if raw_data is not None:
            # 将字节转换为十六进制字符串，每两个字符一个空格
            hex_str = ' '.join(f'{b:02X}' for b in raw_data)
            self.message_display.insert(tk.END, f"[{timestamp}] 原始数据: {hex_str}\n")
        
        self.message_display.see(tk.END)

    def _send_jump_command(self, retry_count=0):
        """发送跳转命令"""
        selected_id = self.id_combobox.get()
        if not selected_id:
            messagebox.showwarning("警告", "请先选择设备ID")
            return False
        
        jump_cmd = {
            "cmd": 995,
            "id": int(selected_id),
            "data1": 0x5550,  # "UP"
            "data2": 0x4441,  # "DA"
            "data3": 0x5441,  # "TA"
            "data4": 0x3F00   # "?"
        }
        
        # 第一次发送跳转指令
        self.network_manager.send_message(json.dumps(jump_cmd))
        self._display_sent_message(jump_cmd)
        
        # 等待100ms
        time.sleep(0.1)
        
        # 第二次发送跳转指令
        self.network_manager.send_message(json.dumps(jump_cmd))
        self._display_sent_message(f"重发跳转指令: {json.dumps(jump_cmd)}")
        
        # 注册回调函数处理回包
        self.network_manager.on_receive_message = lambda msg: self._handle_jump_response(msg, retry_count)
        return True

    def _handle_jump_response(self, message, retry_count):
        """处理跳转指令回包"""
        try:
            data = json.loads(message)
            selected_id = self.id_combobox.get()
            if (data.get("cmd") == 995 and 
                "id" in data and 
                str(data["id"]) == selected_id and
                self.upgrade_state == "JUMP"):
                # 显示回包信息
                timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
                self.message_display.insert(tk.END, f"[{timestamp}] 接收: {json.dumps(data)}\n")
                self.message_display.see(tk.END)

                # 判断回包状态
                if ((data.get("data1") == 0x4A50 and data.get("data2") == 0x4D50) or  # "JPMP"
                    (data.get("data1") == 0x5550 and data.get("data2") == 0x4441 and  # "UPDA"
                     data.get("data4") == 0x4F4B)):  # "OK"
                    # 跳转成功，发送擦除指令
                    self.upgrade_state = "ERASE"
                    self.stop_jump_retry = True  # 停止重试
                    # 清除之前的回调函数
                    self.network_manager.on_receive_message = None
                    self._send_erase_command()
                else:
                    # 手工测试模式 - 已屏蔽重试机制
                    messagebox.showerror("错误", "跳转指令失败，请检查设备状态")
                    self.upgrade_in_progress = False
        except Exception as e:
            messagebox.showerror("错误", f"处理跳转回包时出错: {str(e)}")
            self.upgrade_in_progress = False

    def _send_erase_command(self):
        """发送擦除命令"""
        selected_id = self.id_combobox.get()
        if not selected_id:
            messagebox.showwarning("警告", "请先选择设备ID")
            return False

        # 清除之前的回调函数
        self.network_manager.on_receive_message = None

        erase_cmd = {
            "cmd": 995,  # 与跳转指令相同
            "id": int(selected_id),  # 与跳转指令相同
            "data1": 0x4552,  # "ER"
            "data2": 0x4153,  # "AS"
            "data3": 0x4500,  # "E\0"
            "data4": 0x0000   # "\0\0"
        }

        self.network_manager.send_message(json.dumps(erase_cmd))
        self._display_sent_message(erase_cmd)
        
        # 注册新的回调函数处理回包
        self.network_manager.on_receive_message = self._handle_erase_response
        return True

    def _handle_erase_response(self, message):
        """处理擦除指令回包"""
        try:
            data = json.loads(message)
            selected_id = self.id_combobox.get()
            if (data.get("cmd") == 995 and 
                "id" in data and 
                str(data["id"]) == selected_id and
                self.upgrade_state == "ERASE"):
                # 解析回包数据
                data1 = data.get("data1", 0)
                data2 = data.get("data2", 0)
                data3 = data.get("data3", 0)
                data4 = data.get("data4", 0)

                # 显示回包信息
                timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
                self.message_display.insert(tk.END, f"[{timestamp}] 接收: {json.dumps(data)}\n")
                self.message_display.see(tk.END)

                # 判断回包状态
                if data1 == 0x494E and data2 == 0x4700 and data3 == 0x0000 and data4 == 0x0000:
                    # 正在擦除，继续等待
                    self.message_display.insert(tk.END, "设备正在擦除中，请等待...\n")
                elif data1 == 0x4552 and data2 == 0x4153 and data3 == 0x4545 and data4 == 0x5252:
                    # 擦除失败
                    timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
                    self.message_display.insert(tk.END, f"[{timestamp}] 擦除失败，正在重试... (重试次数: {self.erase_retry_count+1}/{self.MAX_ERASE_RETRY})\n")
                    self.message_display.see(tk.END)
                    
                    if self.erase_retry_count < self.MAX_ERASE_RETRY:
                        self.erase_retry_count += 1
                        # 延迟500毫秒后重发擦除指令
                        self.root.after(500, self._send_erase_command)
                    else:
                        # 达到最大重试次数，终止升级
                        self.message_display.insert(tk.END, f"[{timestamp}] 擦除失败，已达最大重试次数\n")
                        self.message_display.see(tk.END)
                        self.upgrade_in_progress = False
                elif data1 == 0x4552 and data2 == 0x4153 and data3 == 0x4500 and data4 == 0x4F4B:
                    # 擦除成功，开始发送固件
                    self.upgrade_state = "UPGRADE"
                    self._send_upgrade_data()
                else:
                    messagebox.showwarning("警告", "未知的擦除回包状态")
            else:
                # 非擦除回包，忽略
                pass
        except json.JSONDecodeError:
            messagebox.showerror("错误", "回包JSON解析失败")
        except Exception as e:
            messagebox.showerror("错误", f"处理擦除回包时出错: {str(e)}")
            self.upgrade_in_progress = False

    def _crc16_modbus(self, data):
        """
        实现与设备端完全一致的Modbus CRC16校验算法
        算法来自用户提供的C代码
        """
        uchCRCHi = 0xFF
        uchCRCLo = 0xFF
        
        # Modbus CRC16查表
        auchCRCHi = [
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
            0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
            0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
            0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
        ]
        
        auchCRCLo = [
            0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
            0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
            0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
            0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
            0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
            0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
            0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
            0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
            0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
            0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
            0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
            0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
            0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
            0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
            0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
            0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
            0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
            0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
            0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
            0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
            0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
            0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
            0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
            0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
            0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
            0x43, 0x83, 0x41, 0x81, 0x80, 0x40
        ]
        
        for byte in data:
            uIndex = uchCRCHi ^ byte
            uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]
            uchCRCLo = auchCRCLo[uIndex]
        
        return (uchCRCLo << 8) | uchCRCHi

    def _send_upgrade_data(self):
        """发送升级数据(分帧发送) - 异步版本"""
        try:
            if not hasattr(self, 'bin_data'):
                messagebox.showerror("错误", "未加载固件文件")
                return False

            selected_id = self.id_combobox.get()
            if not selected_id:
                messagebox.showwarning("警告", "请先选择设备ID")
                return False

            # 分帧发送数据
            self.frame_size = 8  # 每帧8字节
            self.total_frames = (len(self.bin_data) + self.frame_size - 1) // self.frame_size
            self.current_frame = 0
            self.frame_retry_count = 0
            self.MAX_FRAME_RETRY = 3  # 最大重试次数

            # 注册回包处理函数
            self.network_manager.on_receive_message = self._handle_upgrade_response

            # 开始发送第一帧
            self._send_next_frame()
            return True

        except Exception as e:
            messagebox.showerror("错误", f"发送升级数据失败: {str(e)}")
            self.upgrade_in_progress = False
            return False

    def _send_next_frame(self):
        """发送下一帧数据"""
        if self.current_frame >= self.total_frames:
            messagebox.showinfo("成功", "固件升级完成")
            self.upgrade_in_progress = False
            return

        try:
            # 计算当前帧数据
            i = self.current_frame * self.frame_size
            chunk = self.bin_data[i:i+self.frame_size]
            
            # 最后一帧不足8字节补0xFF
            if len(chunk) < self.frame_size:
                chunk += b'\xFF' * (self.frame_size - len(chunk))
            
            # 计算CRC16
            crc = self._crc16_modbus(chunk)
            
            # 将8字节数据分成4个2字节的data字段
            data1, data2, data3, data4 = struct.unpack('>4H', chunk)
            
            # 添加帧序号到升级命令
            upgrade_cmd = {
                "cmd": 995,
                "id": int(self.id_combobox.get()),
                "data1": data1,
                "data2": data2,
                "data3": data3,
                "data4": data4,
                "frame": self.current_frame + 1  # 帧序号从1开始
            }

            self.network_manager.send_message(json.dumps(upgrade_cmd))
            self._display_sent_message(upgrade_cmd, chunk)
            
            # 更新进度显示
            progress = (self.current_frame + 1) / self.total_frames * 100
            self.progress_var.set(f"发送进度: {progress:.1f}%")
            self.root.update()
            
            # 设置超时重传定时器（2秒）
            self.frame_timeout = self.root.after(2000, self._handle_frame_timeout)

        except Exception as e:
            messagebox.showerror("错误", f"发送帧{self.current_frame+1}失败: {str(e)}")
            self.upgrade_in_progress = False

    def _handle_frame_timeout(self):
        """处理帧发送超时"""
        if self.frame_retry_count < self.MAX_FRAME_RETRY:
            self.frame_retry_count += 1
            timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
            self.message_display.insert(tk.END, f"[{timestamp}] 帧{self.current_frame+1}超时，重试({self.frame_retry_count}/{self.MAX_FRAME_RETRY})\n")
            self.message_display.see(tk.END)
            self._send_next_frame()  # 重发当前帧
        else:
            timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
            self.message_display.insert(tk.END, f"[{timestamp}] 帧{self.current_frame+1}达到最大重试次数，升级终止\n")
            self.message_display.see(tk.END)
            self.upgrade_in_progress = False

    def _handle_frame_error(self):
        """处理帧错误（如CRC校验失败）"""
        if self.frame_retry_count < self.MAX_FRAME_RETRY:
            self.frame_retry_count += 1
            timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
            self.message_display.insert(tk.END, f"[{timestamp}] 帧{self.current_frame+1}错误，重试({self.frame_retry_count}/{self.MAX_FRAME_RETRY})\n")
            self.message_display.see(tk.END)
            self._send_next_frame()  # 重发当前帧
        else:
            timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
            self.message_display.insert(tk.END, f"[{timestamp}] 帧{self.current_frame+1}达到最大重试次数，升级终止\n")
            self.message_display.see(tk.END)
            self.upgrade_in_progress = False

    def _handle_upgrade_response(self, message):
        """处理升级数据回包 - 异步版本"""
        try:
            data = json.loads(message)
            if data.get("cmd") == 995 and "id" in data:
                # 显示回包信息
                timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
                self.message_display.insert(tk.END, f"[{timestamp}] 接收: {json.dumps(data)}\n")
                self.message_display.see(tk.END)
                
                # 解析设备返回的帧序号 (data2和data3的高八位组成)
                data2 = data.get("data2", 0)
                data3 = data.get("data3", 0)
                actual_frame = (data2 << 8) | (data3 >> 8)
                expected_frame = self.current_frame + 1

                # 检查帧计数是否匹配
                if actual_frame == expected_frame:
                    # 取消当前帧的超时定时器
                    if hasattr(self, 'frame_timeout'):
                        self.root.after_cancel(self.frame_timeout)
                        del self.frame_timeout
                    
                    # 验证CRC校验结果
                    received_crc = data.get("data1", 0)
                    # 获取当前帧的原始数据
                    frame_index = self.current_frame * self.frame_size
                    chunk = self.bin_data[frame_index:frame_index+self.frame_size]
                    if len(chunk) < self.frame_size:
                        chunk += b'\xFF' * (self.frame_size - len(chunk))
                    calculated_crc = self._crc16_modbus(chunk)
                    
                    if received_crc == calculated_crc:
                        # 显示成功消息
                        self.message_display.insert(tk.END, f"[{timestamp}] 帧{expected_frame} 接收成功 (CRC校验通过)\n")
                        self.message_display.see(tk.END)
                        
                        # 重置重试计数器
                        self.frame_retry_count = 0
                        
                        # 发送下一帧
                        self.current_frame += 1
                        self._send_next_frame()
                    else:
                        # CRC校验失败
                        self.message_display.insert(tk.END, f"[{timestamp}] 帧{expected_frame} CRC校验失败 (接收:0x{received_crc:04X}, 计算:0x{calculated_crc:04X})\n")
                        self.message_display.see(tk.END)
                        self._handle_frame_error()
                else:
                    # 忽略非当前帧的回包
                    timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
                    self.message_display.insert(tk.END, f"[{timestamp}] 忽略帧{actual_frame}回包 (期望:{expected_frame})\n")
                    self.message_display.see(tk.END)
            else:
                # 非升级回包，忽略
                pass

        except json.JSONDecodeError:
            # 显示错误信息
            timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
            self.message_display.insert(tk.END, f"[{timestamp}] 回包JSON解析失败: {message}\n")
            self.message_display.see(tk.END)
        except Exception as e:
            timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
            self.message_display.insert(tk.END, f"[{timestamp}] 处理升级回包时出错: {str(e)}\n")
            self.message_display.see(tk.END)
            # 发生错误时终止升级
            self.upgrade_in_progress = False

    def send_infrared_count(self):
        """发送红外统计请求"""
        selected_id = self.id_combobox.get()
        if not selected_id:
            messagebox.showwarning("警告", "请先选择设备ID")
            return

        count_cmd = {
            "cmd": 997,
            "id": int(selected_id),
            "data1": 0x494E,  # "IN"
            "data2": 0x4652,  # "FR"
            "data3": 0x0000,
            "data4": 0x0000
        }

        self.network_manager.send_message(json.dumps(count_cmd))
        self._display_sent_message(count_cmd)

    def send_weight_count(self):
        """发送称重统计请求"""
        count_cmd = {
            "cmd": 211
        }

        self.network_manager.send_message(json.dumps(count_cmd))
        self._display_sent_message(count_cmd)
        
        # 注册回调函数处理回包
        self.network_manager.on_receive_message = self._handle_weight_response

    def _handle_weight_response(self, message):
        """处理称重统计回包"""
        try:
            data = json.loads(message)
            if data.get("cmd") == 211:  # 只处理cmd=211的回包
                # 显示回包信息
                timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
                self.message_display.insert(tk.END, f"[{timestamp}] 接收: {json.dumps(data)}\n")
                self.message_display.see(tk.END)

                # 更新统计结果显示
                count = data.get("count", 0)
                id_list = data.get("id", [])
                
                self.count_label.config(text=str(count))
                self.id_list_label.config(text=str(id_list))
                
                # 更新设备ID下拉框
                if id_list:
                    self.id_combobox['values'] = id_list
                    self.id_combobox.current(0)  # 默认选择第一个ID
                
        except json.JSONDecodeError:
            messagebox.showerror("错误", "回包JSON解析失败")
        except Exception as e:
            messagebox.showerror("错误", f"处理称重回包时出错: {str(e)}")
